package com.blah.gwtgames.client.mines;

import com.blah.gwtgames.client.common.ui.SpecialClickListener;
import com.blah.gwtgames.client.common.ui.SpecialImage;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ClickListener;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;

public class Tile extends Composite implements ClickListener, SpecialClickListener {
	private SpecialImage image;
	private int xPos;
	private int yPos;
	private int adjacentMines;
	private boolean isCovered;
	private boolean isMined;
	private boolean isFlagged;
	private Grid grid;
	
	private static String[] imageUrls = new String[14];
	private static int COVERED = 9;
	private static int FLAGGED = 10;
	private static int EXPLODED = 11;
	private static int REVEALED = 12;
	private static int CORRECT = 13;
	
	
	public static void prefetchImages()
	{
		imageUrls[0] = "images/mines/empty.png";
		imageUrls[1] = "images/mines/one.png";
		imageUrls[2] = "images/mines/two.png";
		imageUrls[3] = "images/mines/three.png";
		imageUrls[4] = "images/mines/four.png";
		imageUrls[5] = "images/mines/five.png";
		imageUrls[6] = "images/mines/six.png";
		imageUrls[7] = "images/mines/seven.png";
		imageUrls[8] = "images/mines/eight.png";
		
		imageUrls[COVERED] = "images/mines/covered.png";
		imageUrls[FLAGGED] = "images/mines/flagged.png";
		imageUrls[EXPLODED] = "images/mines/exploded.png";
		imageUrls[REVEALED] = "images/mines/revealed.png";
		imageUrls[CORRECT] = "images/mines/correct.png";
		
		for (int i = 0; i < imageUrls.length; i++)
		{
			Image.prefetch(imageUrls[i]);
		}
	}
	
	public Tile(Grid grid, int x, int y)
	{
		this.grid = grid;
		xPos = x;
		yPos = y;
		
		isCovered = false;
		isMined = false;
		isFlagged = false;
		
		image = new SpecialImage();
		image.addClickListener(this);
		image.addSpecialClickListener(this);
		initWidget(image);
	}
	
	public void reset()
	{
		isCovered = true;
		isMined = false;
		isFlagged = false;
		adjacentMines = 0;
		updateImage();
	}
	
	public boolean isCovered() {return isCovered;}
	public boolean isMined() {return isMined;}
	public boolean isFlagged() {return isFlagged;}
	public int adjacentMines() {return adjacentMines;}
	
	public void toggleFlag() 
	{
		isFlagged = !isFlagged;
		updateImage();
	}
	
	public void placeMine()
	{
		isMined = true;
		Iterator tile = adjacentTiles().iterator();
		while (tile.hasNext())
		{
			((Tile)tile.next()).adjacentMines++;
		}
	}
	
	public int getX() {return xPos;}
	public int getY() {return yPos;}
	
	public int uncover()
	{
		int count = 0;
		
		if (isCovered)
		{
			count = 1;
			isCovered = false;
			
			if (isMined)
			{
				count = -1;
			}
			else
			{
				if (adjacentMines() == 0)
				{
					Iterator iterator = adjacentTiles().iterator();
					while (iterator.hasNext())
					{
						Tile tile = (Tile)iterator.next();
						if (!tile.isFlagged())
							count += tile.uncover();
					}
				}
			}

			updateImage();
		}
		
		return count;
	}
	
	public Set adjacentTiles()
	{
		Set tiles = new HashSet();
		
		for (int x = xPos - 1; x <= xPos + 1; x++)
		{
			if (x >= 0 && x < grid.getWidth())
			{
				for (int y = yPos - 1; y <= yPos + 1; y++)
				{
					if (y >= 0 && y < grid.getHeight())
					{
						Tile tile = grid.getTile(x, y);
						
						if (tile != this)
							tiles.add(tile);
					}
				}
			}
		}
		
		return tiles;
	}
	
	public void onClick(Widget sender)
	{
		grid.onClick(this);
	}
	
	public void onSpecialClick(Widget sender)
	{
		grid.onSpecialClick(this);
	}
	
	public void updateImage()
	{
		int index = 0;
		
		if (isCovered)
		{
			if (grid.getGameState() == Grid.FINISHED)
			{
				if (isMined)
				{
					if (isFlagged)
					{
						index = CORRECT;
					}
					else
					{
						index = REVEALED;
					}
				}
				else
				{
					if (isFlagged)
					{
						index = FLAGGED;
					}
					else
					{
						index = COVERED;
					}
				}
			}
			else
			{
				if (isFlagged)
				{
					index = FLAGGED;
				}
				else
				{
					index = COVERED;
				}
			}
		}
		else
		{
			if (isMined)
			{
				index = EXPLODED;
			}
			else
			{
				index = adjacentMines();
			}
		}
		
		image.setUrl(imageUrls[index]);
	}
}
